﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows;
using iNet.Collections;

namespace iNet.Media.Imaging.Exif
{
	#region ExifColorSpace
	/// <summary>
	/// 表示 EXIF 中繼資料中的色彩呈現。
	/// </summary>
	// Exif2-2.PDF P.32
	public enum ExifColorSpace
	{
		sRGB = 1,
		Uncalibrated = 0xFFFF,
	}
	#endregion
	#region ExifExposureProgram
	/// <summary>
	/// 表示 EXIF 中繼資料中的曝光程式。
	/// </summary>
	// Exif2-2.PDF P.38
	public enum ExifExposureProgram
	{
		Manual = 1,
		NormalProgram = 2,
		AperturePriority = 3,
		ShutterPriority = 4,
		CreativeProgram = 5,
		ActionProgram = 6,
		PortraitMode = 7,
		LandscapeMode = 8,
	}
	#endregion
	#region ExifLightSource
	/// <summary>
	/// 表示 EXIF 中繼資料中的光源資訊。
	/// </summary>
	// Exif2-2.PDF P.41
	public enum ExifLightSource
	{
		Unknown = 0,
		Daylight = 1,
		Fluorescent = 2,
		Tungsten = 3,
		Flash = 4,
		FineWeather = 9,
		CloudyWeather = 10,
		Shade = 11,
		DaylightFluorescent = 12,
		DayWhiteFluorescent = 13,
		CoolWhiteFluorescent = 14,
		WhiteFluorescent = 15,
		StandardLightA = 17,
		StandardLightB = 18,
		StandardLightC = 19,
		D55 = 20,
		D65 = 21,
		D75 = 22,
		D50 = 23,
		IsoStudioTungsten = 24,
		Other = 255,
	}
	#endregion
	#region ExifResolutionUnit
	/// <summary>
	/// 表示 EXIF 中繼資料中的解析度單位。
	/// </summary>
	// Exif2-2.PDF P.26
	public enum ExifResolutionUnit
	{
		Inches = 2,
		Centimeters = 3,
	}
	#endregion
	#region ExifTag
	/// <summary>
	/// 表示 EXIf Tag。
	/// </summary>
	public class ExifTag : ICloneable
	{
		#region 欄位
		BitConverter _BitConverter = BitConverter.LittleEndian;
		uint _Count;
		byte[] _Data;
		ushort _ID;
		Ifd _IFD = Ifd.ExifIfd;
		ExifTagType _Type;
		#endregion
		#region 建構子
		private ExifTag(ExifTag tag)
		{
			_BitConverter = tag._BitConverter;
			_Count = tag._Count;
			_Data = (tag._Data != null ? (tag._Data.Clone() as byte[]) : null);
			_ID = tag._ID;
			_IFD = tag._IFD;
			_Type = tag._Type;
		}
		/// <summary>
		/// 初始化新的 ExifTag 執行個體。
		/// </summary>
		public ExifTag()
		{ }
		/// <summary>
		/// 初始化新的 ExifTag 執行個體。
		/// </summary>
		/// <param name="ifd">所屬的 IFD。</param>
		/// <param name="id">Tag ID。</param>
		/// <param name="type">資料格式。</param>
		/// <param name="count">資料個數。</param>
		/// <param name="data">原始資料。</param>
		/// <exception cref="ArgumentException">無效的 IFD。</exception>
		public ExifTag(Ifd ifd, ushort id, ExifTagType type, uint count, byte[] data)
			: this(BitConverter.LittleEndian, ifd, id, type, count, data)
		{ }
		/// <summary>
		/// 初始化新的 ExifTag 執行個體。
		/// </summary>
		/// <param name="bitConverter">使用的 BitConverter 物件。</param>
		/// <param name="ifd">所屬的 IFD。</param>
		/// <param name="id">Tag ID。</param>
		/// <param name="type">資料格式。</param>
		/// <param name="count">資料個數。</param>
		/// <param name="data">原始資料。</param>
		/// <exception cref="ArgumentNullException">bitConverter 為 Null (Visual Basic 為 Nothing)。</exception>
		/// <exception cref="ArgumentException">無效的 IFD。</exception>
		public ExifTag(BitConverter bitConverter, Ifd ifd, ushort id, ExifTagType type, uint count, byte[] data)
		{
			//確認參數
			if (bitConverter == null)
				throw new ArgumentNullException("bitConverter");
			if (!ifd.IsDefined())
				throw new ArgumentException();

			//初始化
			_BitConverter = bitConverter;
			_IFD = ifd;
			_ID = id;
			_Type = type;
			_Count = count;
			_Data = data;
		}
		/// <summary>
		/// 以指定的資料流初始化 TiffIFDEntry 結構欄位。
		/// </summary>
		/// <param name="stream">提供資料的資料流。</param>
		/// <param name="headerPosition">TIFF 檔案起始位置。</param>
		/// <param name="bitConverter">提供資料轉換的 BitConverter 物件。</param>
		/// <param name="ifd">所屬的 IFD。</param>
		/// <exception cref="ArgumentException">無效的 IFD。</exception>
		/// <exception cref="ArgumentNullException">stream 或 bitConverter 為 Null (Visual Basic 為 Nothing)。</exception>
		public ExifTag(Stream stream, long headerPosition, BitConverter bitConverter, Ifd ifd)
		{
			//確認
			if (stream == null)
				throw new ArgumentNullException("stream");
			if (bitConverter == null)
				throw new ArgumentNullException("bitConverter");
			if (!ifd.IsDefined())
				throw new ArgumentException();

			//讀取資料
			byte[] buffer = new byte[12];
			if (stream.Read(buffer, 0, 12) < 12)
				throw new EndOfStreamException();

			//設定欄位
			_BitConverter = bitConverter;
			_IFD = ifd;
			_ID = bitConverter.ToUInt16(buffer, 0);
			_Type = (ExifTagType)bitConverter.ToUInt16(buffer, 2);
			_Count = bitConverter.ToUInt32(buffer, 4);

			//計算資料長度
			int length;
			switch (this.Type)
			{
				case ExifTagType.AsciiString:
				case ExifTagType.Byte:
				case ExifTagType.SByte:
					length = 1;
					break;
				case ExifTagType.Int16:
				case ExifTagType.UInt16:
					length = 2;
					break;
				case ExifTagType.Int32:
				case ExifTagType.Single:
				case ExifTagType.UInt32:
					length = 4;
					break;
				case ExifTagType.Double:
				case ExifTagType.Rational:
				case ExifTagType.URational:
					length = 8;
					break;
				default:		//當成 byte[4]
					length = 1;
					this.Count = 4;
					break;
			}
			length *= (int)this.Count;

			//讀取資料
			if (length <= 4)
			{
				this.Data = new byte[length];
				Array.Copy(buffer, 8, this.Data, 0, length);
			}
			else
			{
				//建立陣列
				this.Data = new byte[length];

				//取得資料位移
				uint offset = bitConverter.ToUInt32(buffer, 8);

				//確認資料流長度
				long? maxDataLength;
				try
				{
					if (stream.CanSeek)
						maxDataLength = stream.Length - (headerPosition + offset);
					else
						maxDataLength = null;
				}
				catch
				{
					maxDataLength = null;
				}
				if (maxDataLength != null && length > maxDataLength)
					throw new EndOfStreamException();

				//移動資料流位置
				long currPosition = stream.Position;
				stream.Position = headerPosition + offset;

				//讀取
				try
				{
					if (stream.Read(this.Data, 0, length) < length)
						throw new EndOfStreamException();
				}
				finally
				{
					//恢復資料流位置
					stream.Position = currPosition;
				}
			}
		}
		/// <summary>
		/// 初始化新的 ExifTag 執行個體。
		/// </summary>
		/// <param name="bitConverter">使用的 BitConverter 物件，Null (Visual Basic 為 Nothing) 表示使用 Little-Endian 的 BitConverter。</param>
		/// <param name="ifd">所屬的 IFD。</param>
		/// <param name="id">Tag ID。</param>
		/// <param name="value">Tag 的內容值。</param>
		/// <exception cref="ArgumentException">value 為不支援的型別。</exception>
		/// <exception cref="ArgumentNullException">value 為 Null (Visual Basic 為 Nothing)。</exception>
		public ExifTag(BitConverter bitConverter, Ifd ifd, ushort id, object value)
		{
			//確認參數
			if (value == null)
				throw new ArgumentNullException("value");

			//初始化
			this.Initialize(bitConverter, ifd, id, value);
		}
		#endregion
		#region BitConverter
		/// <summary>
		/// 取得或設定使用的 BitConverter 物件。
		/// </summary>
		public BitConverter BitConverter
		{
			get
			{
				return _BitConverter;
			}
			set
			{
				_BitConverter = value;
			}
		}
		#endregion
		#region Clone
		/// <summary>
		/// 建立副本。
		/// </summary>
		/// <returns>EXIF Tag 副本。</returns>
		public ExifTag Clone()
		{
			return new ExifTag(this);
		}
		#endregion
		#region Count
		/// <summary>
		/// 取得或設定資料個數。
		/// </summary>
		public uint Count
		{
			get
			{
				return _Count;
			}
			set
			{
				_Count = value;
			}
		}
		#endregion
		#region Data
		/// <summary>
		/// 取得或設定 Tag 的資料。
		/// </summary>
		public byte[] Data
		{
			get
			{
				return _Data;
			}
			set
			{
				_Data = value;
			}
		}
		#endregion
		#region ExtractValue
		/// <summary>
		/// 取得 EXIF Tag 的實際內容值。
		/// </summary>
		/// <returns>EXIF Tag 的內容值。</returns>
		public unsafe object ExtractValue()
		{
			switch (_Type)
			{
				case ExifTagType.AsciiString:
					if (_Data.Length > 1)
						return Encoding.Default.GetString(_Data, 0, _Data.Length - 1).TrimEnd('\0');
					return "";
				case ExifTagType.Double:
					{
						int length = (int)Math.Min(_Count, _Data.Length / 8);
						if (length == 1)
							return _BitConverter.ToDouble(_Data);
						return _Data.ToDoubleArray(_BitConverter, length);
					}
				case ExifTagType.Int16:
					{
						int length = (int)Math.Min(_Count, _Data.Length / 2);
						if (length == 1)
							return _BitConverter.ToInt16(_Data);
						return _Data.ToInt16Array(_BitConverter, length);
					}
				case ExifTagType.Int32:
					{
						int length = (int)Math.Min(_Count, _Data.Length / 4);
						if (length == 1)
							return _BitConverter.ToInt32(_Data);
						return _Data.ToInt32Array(_BitConverter, length);
					}
				case ExifTagType.Rational:
					{
						int length = (int)Math.Min(_Count, _Data.Length / 8);
						if (length == 1)
							return new Rational(_BitConverter.ToInt32(_Data, 4), _BitConverter.ToInt32(_Data));
						Rational[] array = new Rational[length];
						for (int i = length - 1, offset = (i * 8); i >= 0; --i, offset -= 8)
							array[i] = new Rational(_BitConverter.ToInt32(_Data, offset + 4), _BitConverter.ToInt32(_Data, offset));
						return array;
					}
				case ExifTagType.SByte:
					{
						int length = (int)Math.Min(_Count, _Data.Length);
						if (length == 1)
							return (sbyte)_Data[0];
						return _Data.ToSByteArray(length);
					}
				case ExifTagType.Single:
					{
						int length = (int)Math.Min(_Count, _Data.Length / 4);
						if (length == 1)
							return _BitConverter.ToInt32(_Data);
						return _Data.ToSingleArray(_BitConverter, length);
					}
				case ExifTagType.UInt16:
					{
						int length = (int)Math.Min(_Count, _Data.Length / 2);
						if (length == 1)
							return _BitConverter.ToUInt16(_Data);
						return _Data.ToUInt16Array(_BitConverter, length);
					}
				case ExifTagType.UInt32:
					{
						int length = (int)Math.Min(_Count, _Data.Length / 4);
						if (length == 1)
							return _BitConverter.ToUInt32(_Data);
						return _Data.ToUInt32Array(_BitConverter, length);
					}
				case ExifTagType.URational:
					{
						int length = (int)Math.Min(_Count, _Data.Length / 8);
						if (length == 1)
							return new URational(_BitConverter.ToUInt32(_Data, 4), _BitConverter.ToUInt32(_Data));
						URational[] array = new URational[length];
						for (int i = length - 1, offset = (i * 8); i >= 0; --i, offset -= 8)
							array[i] = new URational(_BitConverter.ToUInt32(_Data, offset + 4), _BitConverter.ToUInt32(_Data, offset));
						return array;
					}
			}
			if (Math.Min(_Count, (uint)_Data.Length) == 1)
				return _Data[0];
			return _Data;
		}
		#endregion
		#region GetElementSize
		/// <summary>
		/// 取得指定格式的資料位元組長度。
		/// </summary>
		/// <param name="type">資料格式。</param>
		/// <returns>資料位元組長度，0 表示未定義。</returns>
		public static int GetElementSize(ExifTagType type)
		{
			switch(type)
			{
				case ExifTagType.AsciiString:
				case ExifTagType.Byte:
				case ExifTagType.SByte:
					return 1;
				case ExifTagType.Int16:
				case ExifTagType.UInt16:
					return 2;
				case ExifTagType.Int32:
				case ExifTagType.UInt32:
				case ExifTagType.Single:
					return 4;
				case ExifTagType.Double:
				case ExifTagType.Rational:
				case ExifTagType.URational:
					return 8;
				default:
					return 0;
			}
		}
		#endregion
		#region ICloneable.Clone
		object ICloneable.Clone()
		{
			return new ExifTag(this);
		}
		#endregion
		#region ID
		/// <summary>
		/// 取得或設定 Tag ID。
		/// </summary>
		public ushort ID
		{
			get
			{
				return _ID;
			}
			set
			{
				_ID = value;
			}
		}
		#endregion
		#region Ifd
		/// <summary>
		/// 取得或設定所屬的 IFD (Image File Directory)。
		/// </summary>
		public Ifd Ifd
		{
			get
			{
				return _IFD;
			}
			set
			{
				if (!value.IsDefined())
					throw new ArgumentException();
				_IFD = value;
			}
		}
		#endregion
		#region Initialize
		void Initialize(BitConverter bitConverter, Ifd ifd, ushort id, object value)
		{
			//初始化基本屬性
			_BitConverter = (bitConverter != null ? bitConverter : BitConverter.LittleEndian);
			_IFD = ifd;
			_ID = id;

			//轉換日期時間
			if (value is DateTime)
				value = ((DateTime)value).ToString("yyyy:MM:dd HH:mm:ss");

			//轉換資料
			if (value is string)
			{
				string str = (value as string);
				_Data = new byte[Encoding.Default.GetByteCount(str) + 1];
				Encoding.Default.GetBytes(str, 0, str.Length, _Data, 0);
				_Count = (uint)_Data.Length;
				_Type = ExifTagType.AsciiString;
			}
			else if (value is byte)
			{
				_Data = new byte[] { (byte)value };
				_Count = 1;
				_Type = ExifTagType.Byte;
			}
			else if (value is byte[])
			{
				_Data = ((value as ICloneable).Clone() as byte[]);
				_Count = (uint)_Data.Length;
				_Type = ExifTagType.Byte;
			}
			else if (value is sbyte)
			{
				_Data = new byte[] { (byte)(sbyte)value };
				_Count = 1;
				_Type = ExifTagType.SByte;
			}
			else if (value is sbyte[])
			{
				_Data = (value as sbyte[]).ToBytes();
				_Count = (uint)_Data.Length;
				_Type = ExifTagType.SByte;
			}
			else if (value is short)
			{
				_Data = _BitConverter.GetBytes((short)value);
				_Count = 1;
				_Type = ExifTagType.Int16;
			}
			else if (value is short[])
			{
				_Data = (value as short[]).ToBytes(_BitConverter);
				_Count = (uint)(value as short[]).Length;
				_Type = ExifTagType.Int16;
			}
			else if (value is ushort)
			{
				_Data = _BitConverter.GetBytes((ushort)value);
				_Count = 1;
				_Type = ExifTagType.UInt16;
			}
			else if (value is ushort[])
			{
				_Data = (value as ushort[]).ToBytes(_BitConverter);
				_Count = (uint)(value as ushort[]).Length;
				_Type = ExifTagType.UInt16;
			}
			else if (value is int)
			{
				_Data = _BitConverter.GetBytes((int)value);
				_Count = 1;
				_Type = ExifTagType.Int32;
			}
			else if (value is int[])
			{
				_Data = (value as int[]).ToBytes(_BitConverter);
				_Count = (uint)(value as int[]).Length;
				_Type = ExifTagType.Int32;
			}
			else if (value is uint)
			{
				_Data = _BitConverter.GetBytes((uint)value);
				_Count = 1;
				_Type = ExifTagType.UInt32;
			}
			else if (value is uint[])
			{
				_Data = (value as uint[]).ToBytes(_BitConverter);
				_Count = (uint)(value as uint[]).Length;
				_Type = ExifTagType.UInt32;
			}
			else if (value is float)
			{
				_Data = _BitConverter.GetBytes((float)value);
				_Count = 1;
				_Type = ExifTagType.Single;
			}
			else if (value is float[])
			{
				_Data = (value as float[]).ToBytes(_BitConverter);
				_Count = (uint)(value as float[]).Length;
				_Type = ExifTagType.Single;
			}
			else if (value is double)
			{
				_Data = _BitConverter.GetBytes((double)value);
				_Count = 1;
				_Type = ExifTagType.Double;
			}
			else if (value is double[])
			{
				_Data = (value as double[]).ToBytes(_BitConverter);
				_Count = (uint)(value as double[]).Length;
				_Type = ExifTagType.Double;
			}
			else if (value is Rational)
			{
				Rational rational = (Rational)value;
				_Data = _BitConverter.GetBytes(rational.Numerator).Concat<byte>(_BitConverter.GetBytes(rational.Denominator));
				_Count = 1;
				_Type = ExifTagType.Rational;
			}
			else if (value is Rational[])
			{
				Rational[] array = (value as Rational[]);
				List<byte> dataBuffer = new List<byte>();
				for (int i = 0; i < array.Length; ++i)
				{
					dataBuffer.AddRange(_BitConverter.GetBytes(array[i].Numerator));
					dataBuffer.AddRange(_BitConverter.GetBytes(array[i].Denominator));
				}
				_Data = dataBuffer.ToArray();
				_Count = (uint)array.Length;
				_Type = ExifTagType.Rational;
			}
			else if (value is URational)
			{
				URational rational = (URational)value;
				_Data = _BitConverter.GetBytes(rational.Numerator).Concat<byte>(_BitConverter.GetBytes(rational.Denominator));
				_Count = 1;
				_Type = ExifTagType.URational;
			}
			else if (value is URational[])
			{
				URational[] array = (value as URational[]);
				List<byte> dataBuffer = new List<byte>();
				for (int i = 0; i < array.Length; ++i)
				{
					dataBuffer.AddRange(_BitConverter.GetBytes(array[i].Numerator));
					dataBuffer.AddRange(_BitConverter.GetBytes(array[i].Denominator));
				}
				_Data = dataBuffer.ToArray();
				_Count = (uint)array.Length;
				_Type = ExifTagType.URational;
			}
			else
				throw new ArgumentException("Unsupported value type : " + value.GetType().ToString());
		}
		#endregion
		#region Key
		/// <summary>
		/// 取得 EXIF Tag 的識別碼。
		/// </summary>
		public ExifTagKey Key
		{
			get
			{
				return new ExifTagKey(_IFD, _ID);
			}
		}
		#endregion
		#region ToString
		public override string ToString()
		{
			return string.Format("{0}/{1}", _IFD, _ID);
		}
		#endregion
		#region Type
		/// <summary>
		/// 取得或設定資料格式。
		/// </summary>
		public ExifTagType Type
		{
			get
			{
				return _Type;
			}
			set
			{
				_Type = value;
			}
		}
		#endregion
	}
	#endregion
	#region ExifTagInfo
	/*
	/// <summary>
	/// EXIF Tag 資訊。
	/// </summary>
	public class ExifTagInfo
	{
		#region 欄位
		/// <summary>
		/// Tag ID。
		/// </summary>
		public readonly ushort ID;
		/// <summary>
		/// Tag 所屬的 Image File Directory。
		/// </summary>
		public readonly IFD IFD;
		/// <summary>
		/// 對應的中繼資料名稱。
		/// </summary>
		public readonly string MetadataName;
		/// <summary>
		/// 名稱。
		/// </summary>
		public readonly string Name;
		/// <summary>
		/// 資料格式。
		/// </summary>
		public readonly ExifTagType[] Types;
		#endregion
		#region 建構子
		internal ExifTagInfo(ushort id, IFD ifd, ExifTagType type, string name, string metadataName)
			: this(id, ifd, new ExifTagType[] { type }, name, metadataName)
		{ }
		internal ExifTagInfo(ushort id, IFD ifd, ExifTagType[] types, string name, string metadataName)
		{
			this.ID = id;
			this.IFD = ifd;
			this.MetadataName = metadataName;
			this.Name = name;
			this.Types = types;
		}
		#endregion
	}
	*/
	#endregion
	#region ExifTagKey
	/// <summary>
	/// 表示 EXIF Tag 的識別碼。
	/// </summary>
	public struct ExifTagKey
	{
		#region 欄位
		ushort _ID;
		Ifd _IFD;
		#endregion
		#region 建構子
		/// <summary>
		/// 初始化 ExifTagKey 結構成員。
		/// </summary>
		/// <param name="ifd"></param>
		/// <param name="id"></param>
		public ExifTagKey(Ifd ifd, ushort id)
		{
			_IFD = ifd;
			_ID = id;
		}
		#endregion
		#region ID
		/// <summary>
		/// 取得或設定 Tag ID。
		/// </summary>
		public ushort ID
		{
			get
			{
				return _ID;
			}
			set
			{
				_ID = value;
			}
		}
		#endregion
		#region IFD
		/// <summary>
		/// 取得或設定所屬的 IFD (Image File Directory)。
		/// </summary>
		public Ifd IFD
		{
			get
			{
				return _IFD;
			}
			set
			{
				_IFD = value;
			}
		}
		#endregion
	}
	#endregion
	#region ExifTagNames
	/*
	/// <summary>
	/// 提供 EXIF Tag 名稱。
	/// </summary>
	public static class ExifTagNames
	{
		//EXIF
		public const string ApertureValue = "ApertureValue";
		public const string Artist = "Artist";
		public const string BatteryLevel = "BatteryLevel";
		public const string BitsPerSample = "BitsPerSample";
		public const string BrightnessValue = "BrightnessValue";
		public const string CFAPattern = "CFAPattern";
		public const string CFARepeatPatternDim = "CFARepeatPatternDim";
		public const string ColorSpace = "ColorSpace";
		public const string ComponentsConfiguration = "ComponentsConfiguration";
		public const string CompressedBitsPerPixel = "CompressedBitsPerPixel";
		public const string Compression = "Compression";
		public const string Contrast = "Contrast";
		public const string Copyright = "Copyright";
		public const string CustomRendered = "CustomRendered";
		public const string DateTimeDigitized = "DateTimeDigitized";
		public const string DateTimeModified = "DateTimeModified";
		public const string DateTimeOriginal = "DateTimeOriginal";
		public const string DeviceSettingDescription = "DeviceSettingDescription";
		public const string DigitalZoomRatio = "DigitalZoomRatio";
		public const string EPStandardID = "EPStandardID";
		public const string ExifIfdPointer = "ExifIfdPointer";
		public const string ExifInteroperabilityOffset = "ExifInteroperabilityOffset";
		public const string ExifVersion = "ExifVersion";
		public const string ExposureBiasValue = "ExposureBiasValue";
		public const string ExposureIndex = "ExposureIndex";
		public const string ExposureMode = "ExposureMode";
		public const string ExposureProgram = "ExposureProgram";
		public const string ExposureTime = "ExposureTime";
		public const string FileSource = "FileSource";
		public const string Flash = "Flash";
		public const string FlashEnergy = "FlashEnergy";
		public const string FlashPixVersion = "FlashPixVersion";
		public const string FNumber = "FNumber";
		public const string FocalLength = "FocalLength";
		public const string FocalLengthIn35mmFilm = "FocalLengthIn35mmFilm";
		public const string FocalPlaneResolutionUnit = "FocalPlaneResolutionUnit";
		public const string FocalPlaneXResolution = "FocalPlaneXResolution";
		public const string FocalPlaneYResolution = "FocalPlaneYResolution";
		public const string GainControl = "GainControl";
		public const string GPSAltitude = "GPSAltitude";
		public const string GPSAltitudeRef = "GPSAltitudeRef";
		public const string GPSAreaInformation = "GPSAreaInformation";
		public const string GPSDateStamp = "GPSDateStamp";
		public const string GPSDestBearing = "GPSDestBearing";
		public const string GPSDestBearingRef = "GPSDestBearingRef";
		public const string GPSDestDistance = "GPSDestDistance";
		public const string GPSDestDistanceRef = "GPSDestDistanceRef";
		public const string GPSDestLatitude = "GPSDestLatitude";
		public const string GPSDestLatitudeRef = "GPSDestLatitudeRef";
		public const string GPSDestLongitude = "GPSDestLongitude";
		public const string GPSDestLongitudeRef = "GPSDestLongitudeRef";
		public const string GPSDifferential = "GPSDifferential";
		public const string GPSDOP = "GPSDOP";
		public const string GPSIfdPointer = "GPSIfdPointer";
		public const string GPSImgDirection = "GPSImgDirection";
		public const string GPSImgDirectionRef = "GPSImgDirectionRef";
		public const string GPSLatitude = "GPSLatitude";
		public const string GPSLatitudeRef = "GPSLatitudeRef";
		public const string GPSLongitude = "GPSLongitude";
		public const string GPSLongitudeRef = "GPSLongitudeRef";
		public const string GPSMapDatum = "GPSMapDatum";
		public const string GPSMeasureMode = "GPSMeasureMode";
		public const string GPSProcessingMethod = "GPSProcessingMethod";
		public const string GPSSatellites = "GPSSatellites";
		public const string GPSSpeed = "GPSSpeed";
		public const string GPSSpeedRef = "GPSSpeedRef";
		public const string GPSStatus = "GPSStatus";
		public const string GPSTimeStamp = "GPSTimeStamp";
		public const string GPSTrack = "GPSTrack";
		public const string GPSTrackRef = "GPSTrackRef";
		public const string GPSVersionID = "GPSVersionID";
		public const string ImageDescription = "ImageDescription";
		public const string ImageHeight = "ImageHeight";
		public const string ImageHistory = "ImageHistory";
		public const string ImageNumber = "ImageNumber";
		public const string ImageUniqueID = "ImageUniqueID";
		public const string ImageWidth = "ImageWidth";
		public const string InterColorProfile = "InterColorProfile";
		public const string Interlace = "Interlace";
		public const string InteroperabilityIfdPointer = "InteroperabilityIfdPointer";
		public const string ISOSpeedRatings = "ISOSpeedRatings";
		public const string JpegIFByteCount = "JpegIFByteCount";
		public const string JpegIFOffset = "JpegIFOffset";
		public const string JPEGInterchangeFormat = "JPEGInterchangeFormat";
		public const string JPEGInterchangeFormatLength = "JPEGInterchangeFormatLength";
		public const string JPEGTables = "JPEGTables";
		public const string LightSource = "LightSource";
		public const string Make = "Make";
		public const string MakerNote = "MakerNote";
		public const string MaxApertureValue = "MaxApertureValue";
		public const string MeteringMode = "MeteringMode";
		public const string Model = "Model";
		public const string NAA = "NAA";
		public const string NewSubfileType = "NewSubfileType";
		public const string Noise = "Noise";
		public const string OECF = "OECF";
		public const string Orientation = "Orientation";
		public const string PhotometricInterpretation = "PhotometricInterpretation";
		public const string PixelXDimension = "PixelXDimension";
		public const string PixelYDimension = "PixelYDimension";
		public const string PlanarConfiguration = "PlanarConfiguration";
		public const string Predictor = "Predictor";
		public const string PrimaryChromaticities = "PrimaryChromaticities";
		public const string ReferenceBlackWhite = "ReferenceBlackWhite";
		public const string RelatedSoundFile = "RelatedSoundFile";
		public const string ResolutionUnit = "ResolutionUnit";
		public const string RowsPerStrip = "RowsPerStrip";
		public const string SamplesPerPixel = "SamplesPerPixel";
		public const string Saturation = "Saturation";
		public const string SceneCaptureType = "SceneCaptureType";
		public const string SceneType = "SceneType";
		public const string SecurityClassification = "SecurityClassification";
		public const string SelfTimerMode = "SelfTimerMode";
		public const string SensingMethod = "SensingMethod";
		public const string Sharpness = "Sharpness";
		public const string ShutterSpeedValue = "ShutterSpeedValue";
		public const string Software = "Software";
		public const string SpatialFrequencyResponse = "SpatialFrequencyResponse";
		public const string SpectralSensitivity = "SpectralSensitivity";
		public const string StripByteConunts = "StripByteConunts";
		public const string StripOffsets = "StripOffsets";
		public const string SubfileType = "SubfileType";
		public const string SubIFDs = "SubIFDs";
		public const string SubjectArea = "SubjectArea";
		public const string SubjectDistance = "SubjectDistance";
		public const string SubjectDistanceRange = "SubjectDistanceRange";
		public const string SubjectLocation = "SubjectLocation";
		public const string SubSecTime = "SubSecTime";
		public const string SubSecTimeDigitized = "SubSecTimeDigitized";
		public const string SubSecTimeOriginal = "SubSecTimeOriginal";
		public const string ThumbnailImageLength = "ThumbnailImageLength";
		public const string ThumbnailImageWidth = "ThumbnailImageWidth";
		public const string TileByteCounts = "TileByteCounts";
		public const string TileLength = "TileLength";
		public const string TileOffsets = "TileOffsets";
		public const string TileWidth = "TileWidth";
		public const string TimeZoneOffset = "TimeZoneOffset";
		public const string TransferFunction = "TransferFunction";
		public const string Unknown = "Unknown";
		public const string UserComment = "UserComment";
		public const string WhiteBalance = "WhiteBalance";
		public const string WhitePoint = "WhitePoint";
		public const string XmpPacket = "XmpPacket";
		public const string XResolution = "XResolution";
		public const string YCbCrCoefficients = "YCbCrCoefficients";
		public const string YCbCrPositioning = "YCbCrPositioning";
		public const string YCbCrSubSampling = "YCbCrSubSampling";
		public const string YResolution = "YResolution";

		//Windows 使用的中繼資料
		public const string Windows_Author = "Windows.Author";
		public const string Windows_Comment = "Windows.Comment";
		public const string Windows_Keyword = "Windows.Keyword";
		public const string Windows_Subject = "Windows.Subject";
		public const string Windows_Title = "Windows.Title";
	}
	*/
	#endregion
	#region ExifTagType
	/// <summary>
	/// 表示 EXIF Tag 資料格式。
	/// </summary>
	public enum ExifTagType : ushort
	{
		/// <summary>
		/// 表示未定義，此值不應該出現在檔案中。
		/// </summary>
		Undefined = 0,
		/// <summary>
		/// 位元組。
		/// </summary>
		Byte = 1,
		/// <summary>
		/// ASCII 字串。
		/// </summary>
		AsciiString = 2,
		/// <summary>
		/// 16 位元不帶正負號整數。
		/// </summary>
		UInt16 = 3,
		/// <summary>
		/// 32 位元不帶正負號整數。
		/// </summary>
		UInt32 = 4,
		/// <summary>
		/// 分子分母各為 32 位元不帶正負號整數的分數。
		/// </summary>
		URational = 5,
		/// <summary>
		/// 帶正負號的位元組。
		/// </summary>
		SByte = 6,
		/// <summary>
		/// 16 位元整數。
		/// </summary>
		Int16 = 8,
		/// <summary>
		/// 32 位元整數。
		/// </summary>
		Int32 = 9,
		/// <summary>
		/// 分子分母各為 32 位元整數的分數。
		/// </summary>
		Rational = 10,
		/// <summary>
		/// 單精準浮點數。
		/// </summary>
		Single = 11,
		/// <summary>
		/// 倍精準浮點數。
		/// </summary>
		Double = 12,
	}
	#endregion
	#region Ifd
	/// <summary>
	/// 表示 EXIF 中的 Image File Directory。
	/// </summary>
	public enum Ifd
	{
		Ifd0,
		Ifd1,
		Ifd2,
		Ifd3,
		SubIfd0,
		SubIfd1,
		ExifIfd,
		GpsIfd,
		InteroperabilityIfd,

		CanonMakerNote,
		NikonMakerNoteType1,
		NikonMakerNoteType2,
		NikonMakerNoteType3,
		PentaxMakerNote,
	}
	#endregion
}